package com.henry.jvm;

import java.io.File;
import java.lang.management.ClassLoadingMXBean;
import java.lang.management.ManagementFactory;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;

/**
 * 通过自定义类加载器loadClass导致元数据内存溢出
 * 1.设置jvm参数  -XX:MetaspaceSize=8m -XX:MaxMetaspaceSize=8m
 * 2.通过自定义classloader指定url  loadClass
 * 3.由于java类加载器的双亲委托机制,所以loadClass不能加载本工程的类(包括maven依赖的jar包),因为自定义classloader的父classloader也就是AppClassloader也能加载到本工程的类
 * 4.最终会导致该类仅被AppClassloader加载一次
 */
public class LoadClassOOM {
    public static void main(String[] args) {
                 try {
                     //准备url
                     URL url = new File("D:\\java\\project\\IdeaProjects\\henry\\investment\\target").toURI().toURL();
                     URL[] urls = {url};
                     //获取有关类型加载的JMX接口
                     ClassLoadingMXBean loadingBean = ManagementFactory.getClassLoadingMXBean();
                     //用于缓存类加载器
                     List<ClassLoader> classLoaders = new ArrayList<ClassLoader>();
                     while (true) {
                             //加载类型并缓存类加载器实例
                             ClassLoader classLoader = new URLClassLoader(urls);
                             classLoaders.add(classLoader);
                             classLoader.loadClass("com.investment.main.Client");
                             //显示数量信息（共加载过的类型数目，当前还有效的类型数目，已经被卸载的类型数目）
                             System.out.println("total: " + loadingBean.getTotalLoadedClassCount());
                             System.out.println("active: " + loadingBean.getLoadedClassCount());
                             System.out.println("unloaded: " + loadingBean.getUnloadedClassCount());
                         }
                 } catch (Exception e) {
                     e.printStackTrace();
                 }
            }
}
